#include "hydrology.h"
#include "tpunb.h"
#include <time.h>
#include <devnode.h>
#include <mqtt_client.h>
#include <server.h>
#include "recordModule.h"

unsigned short get_pkg_data_len(unsigned char *pkg)
{
	unsigned short pkg_len;
	pkg_len = ((unsigned short)(pkg[FRAME_OFFSET_PKGBEGIN - 2] & 0x0F) << 8) | pkg[FRAME_OFFSET_PKGBEGIN - 1];	
	return pkg_len;
}

char *get_pkg_dev_sn(unsigned char *pkg, char *dev_sn)
{
	hydrology_head_t *pkgHead;
	pkgHead = (hydrology_head_t *)pkg;
	strcpy(dev_sn, "580");
	devid_to_sn(pkgHead->dev_addr.center_addrs.remoter_addr, &dev_sn[3]);
	return dev_sn;
}

unsigned char* get_pkg_data_addr_ptr(unsigned char *pkg)
{
	return &pkg[FRAME_OFFSET_PKGDATA];
}

//反馈到设备
static void hydrology_heartbeat_response(char *dev_sn)
{
	time_t time_seconds = time(NULL);
    struct tm now_time;
	user_time_t *currentTime;
	unsigned char buf[32];

    localtime_r(&time_seconds, &now_time);
 
    //DEBUG("%d-%d-%d %d:%d:%d tm_wday:%d\n", now_time.tm_year + 1900, now_time.tm_mon + 1,
    //    now_time.tm_mday, now_time.tm_hour, now_time.tm_min, now_time.tm_sec, now_time.tm_wday);
	
	currentTime = (user_time_t *)buf;
	currentTime->year = (now_time.tm_year + 1900) - 2000;
	currentTime->month = now_time.tm_mon + 1;
	currentTime->day = now_time.tm_mday;
	currentTime->hour = now_time.tm_hour;
	currentTime->minute = now_time.tm_min;
	currentTime->second = now_time.tm_sec;
	currentTime->weekday = now_time.tm_wday;

	hydrology_transform(HYD_CMD_ALIVE, buf, sizeof(user_time_t));
}

static void hydrology_heartbeat_process(unsigned char *pkg, int data_type)
{
	DEV_NODE *dev_node;
	char devSN[32] = {0};
	unsigned char *pkg_data;
	unsigned short battery_level = 0;
	unsigned short dev_addr = 0;
	unsigned short lte_csq = 0;
	unsigned short ac_adapter = 0;
	short dev_rssi = 0;		//窄带信号负数
	unsigned short pkg_len;

	get_pkg_dev_sn(pkg, devSN);
	pkg_len = get_pkg_data_len(pkg);
	DEBUG("devSN=%s pkg_len=%d", devSN, pkg_len);

	pkg_data = get_pkg_data_addr_ptr(pkg);
	if(pkg_len >= 6) {
		lte_csq = pkg_data[4];		//4G信号
		ac_adapter = pkg_data[5];	//是否接适配器
		DEBUG("lte_csq=%d ac_adapter=%d", lte_csq, ac_adapter);
	}

	if(pkg_len >= 4) {
		dev_rssi = pkg_data[1]; 		//窄带信号	-127 ~ -1
		dev_addr = ((unsigned short)(pkg_data[2] & 0xFF) << 8) | (pkg_data[3]); //窄带地址
		DEBUG("rssi=%d, addr=%04X", dev_rssi, dev_addr);
	}

	if(pkg_len >= 1) {
		battery_level = pkg_data[0];	//电量
		DEBUG("battery=%d", battery_level);
	}

	dev_node = get_dev_node(devSN);
	if(dev_node) {
		dev_node->battery_level = battery_level;
		dev_node->dev_rssi 		= dev_rssi * -1;
		dev_node->devaddr 		= dev_addr;
		dev_node->lte_csq 		= lte_csq;
		dev_node->ac_adapter 	= ac_adapter;
		dev_node->online = 1;
		dev_node->online_rsp = 1;

		if(DATA_TYPE_MQTT == data_type)
			dev_node->online_lte = 1;
		else if(DATA_TYPE_TPUNB == data_type)
			dev_node->online_tpunb = 1;

		update_devnode_info(dev_node);

		//上报所有状态QT
		dev_status_notify_qt(dev_node);

		//更新qt
		online_state_notify_qt(devSN, 1);
	}

	//反馈到设备
	hydrology_heartbeat_response(devSN);
}

void hydrology_warn_cancle_process(unsigned char *pkg)
{
	DEV_NODE *dev_node;
	char devSN[32] = {0};
	hydrology_param_t hydrology_param = {};

	get_pkg_dev_sn(pkg, devSN);
	DEBUG("%s %s\n", __func__, devSN);

	waring_state_notify_qt(devSN, 1);					//更新QT已应答
	//online_state_notify_qt(devSN, 1);					//更新QT在线

	dev_node = get_dev_node(devSN);
	if(dev_node) {
		
		//之前离线,置为在线
		if(dev_node->online == 0) {
			online_state_notify_qt(devSN, 1);
			dev_node->online = 1;
		}

		//更新已应答状态
		dev_node->warn_rsp_state = 3;
		dev_node->answer_rsp_time = time(NULL);

		memset(&hydrology_param, 0, sizeof(hydrology_param));
		hydrology_param.cmdtype = HYD_CMD_WARNCANCLE;
		hydrology_param.buf = NULL;
		hydrology_param.length = 0;
		hydrology_param.addr = dev_node->devaddr;
		memcpy(hydrology_param.dev_sn, dev_node->dev_sn, sizeof(dev_node->dev_sn));
		//hydrology_transform_enqueue(&hydrology_param);
	}
}

//注意安全 准备转移 立即转移	消警 的指令反馈
void hydrology_warn_process(unsigned char *pkg)
{
	DEV_NODE *dev_node;
	WARN_RSP_DATA rsp_data = {0};
	WARN_RSP_DATA *warn_data = &rsp_data;
	char devSN[32] = {0};
	int pkg_len;

	get_pkg_dev_sn(pkg, devSN);
	//DEBUG("%s %s\n", __func__, devSN);

	pkg_len = get_pkg_data_len(pkg);
	if(pkg_len >= 2) {
		warn_data = (WARN_RSP_DATA *)get_pkg_data_addr_ptr(pkg);
	}

	DEBUG("devSN=%s pkg_len=%d warn_status=%d is_answer=%d", devSN, pkg_len, warn_data->warn_status, warn_data->is_answer);

	dev_node = get_dev_node(devSN);
	if(dev_node) {

		//之前离线,更新为在线状态
		if(dev_node->online == 0) {
			online_state_notify_qt(devSN, 1);
			dev_node->online = 1;
		}
		
		if(warn_data->warn_status > ALARM_STATE_Null && warn_data->warn_status < ALARM_STATE_End) {
			if(ALARM_STATE_Cancel_transfer == warn_data->warn_status) {
				//消警反馈
				dev_node->cancel_rsp_state = 2;
				dev_node->cancel_rsp_time = time(NULL);
				DEBUG("%s cancel_rsp_state=%d", devSN, dev_node->cancel_rsp_state);

				//由已应答状态或未应答状态更新为在线状态
				online_state_notify_qt(devSN, 2);
			} else {
				//报警反馈
				if(warn_data->is_answer) {
					//更新为已应答状态
					dev_node->warn_rsp_state = 3;
					dev_node->answer_rsp_time = time(NULL);
					if(dev_node->warn_rsp_time == 0)
						dev_node->warn_rsp_time = dev_node->answer_rsp_time;
					DEBUG("%s warn_rsp_state=%d", devSN, dev_node->warn_rsp_state);					
					waring_state_notify_qt(devSN, 1);					//更新QT已应答
				} else {
					//更新为已回复状态
					dev_node->warn_rsp_state = 2;
					dev_node->warn_rsp_time = time(NULL);
					DEBUG("%s warn_rsp_state=%d", devSN, dev_node->warn_rsp_state);
					waring_state_notify_qt(devSN, 0);					//更新QT未应答
				}
			}
		}
	}
}

void hydrology_set_dev_netinfo_process(unsigned char *pkg)
{
	char devSN[32] = {0};
	unsigned char *pkg_data;
	unsigned short addr;
	unsigned char cellid;

	get_pkg_dev_sn(pkg, devSN);

	pkg_data = get_pkg_data_addr_ptr(pkg);
	addr = ((unsigned short)(pkg_data[0] & 0xFF) << 8) | pkg_data[1];	
	cellid = pkg_data[2];
	DEBUG("%s addr=%d, cellid=%d\n", __func__, addr, cellid);

	devNode_netInfo_settings_rsp(devSN, addr, cellid);
}

void hydrology_trigger_alarm_process(unsigned char *pkg, int data_type)
{
	typedef struct {
		unsigned short seq;
		unsigned char sendtime[6];
		unsigned char warntime[6];
		unsigned char alarm_type;
		unsigned char alarm_level;
		unsigned char waterlevel[4];
	} __attribute__((aligned(1))) WARN_DESC;

	union BytesToFloat {
		float f;
		unsigned char bytes[4];
	};

	int pkg_len;
	WARN_DESC *warn_desc;
	float waterlevel_f;
	int waterlevel_i;
	union BytesToFloat btf;

	pkg_len = get_pkg_data_len(pkg);
	if(pkg_len < 0x14)
	{
		DEBUG("pkg_len=%d,small pkg", pkg_len);
		return;
	}

	warn_desc = (WARN_DESC *)get_pkg_data_addr_ptr(pkg);

	btf.bytes[0] = warn_desc->waterlevel[3];
	btf.bytes[1] = warn_desc->waterlevel[2];
	btf.bytes[2] = warn_desc->waterlevel[1];
	btf.bytes[3] = warn_desc->waterlevel[0];

	waterlevel_f = btf.f;
	waterlevel_i = waterlevel_f*100;

	DEBUG("alarm_type=%d,alarm_level=%d,waterlevel_f=%0.3f,waterlevel_i=%d", warn_desc->alarm_type, warn_desc->alarm_level, waterlevel_f, waterlevel_i);

	if(warn_desc->alarm_level >= 1 && warn_desc->alarm_level <= 3)
	{
		//更新UI水位值
		water_level_notify_qt(waterlevel_i);

		//弹出qt注意安全界面
		//trigger_alarm_notify_qt(warn_desc->alarm_level);

		//停止播报
		stop_voice_broadcast();

		//播报注意安全语音
		start_voice_broadcast(warn_desc->alarm_level, 0);

		//最高报警
		if(warn_desc->alarm_level == 3 && data_type == DATA_TYPE_TPUNB)
		{
			//广播到报警器
			dev_warn_notify(NULL, ALARM_STATE_Immediate_transfer);
		}
	}
	else
	{
		//上报0,非报警值
		trigger_alarm_notify_qt(0);

		//停止播报
		stop_voice_broadcast();

		//广播到报警器消警
		dev_warn_notify(NULL, ALARM_STATE_Cancel_transfer);
	}
}

//update qt ui
void hydrology_water_level_process(unsigned char *pkg)
{
	int pkg_len;
	int water_level = 0;
	char water_level_str[16] = {0};

	int rain_level = 0;
	char rain_level_str[16] = {0};

#if 0
	static int warn_level_1_t = 0;
	static int warn_level_2_t = 0;
	static int warn_level_3_t = 0;

	time_t now;
	now = time(NULL);
#endif

	hydrology_head_t *pkgHead;
	pkgHead = (hydrology_head_t *)pkg;

	pkg_len = get_pkg_data_len(pkg);

	//DEBUG("pkg_len=%02X", pkg_len);
	if(pkg_len == 0x26)
	{
		hex2string(rain_level_str, &pkg[39], 3);
		rain_level = atoi(rain_level_str) * 10;
		DEBUG("rain_level=%s  %d", rain_level_str, rain_level);

		hex2string(water_level_str, &pkg[44], 4);
		water_level = atoi(water_level_str);
		DEBUG("water_level=%s  %d", water_level_str, water_level);
	}
	else if(pkg_len == 0x2B)
	{
		hex2string(rain_level_str, &pkg[44], 3);
		rain_level = atoi(rain_level_str) * 10;
		DEBUG("rain_level=%s  %d", rain_level_str, rain_level);

		hex2string(water_level_str, &pkg[49], 4);
		water_level = atoi(water_level_str) / 10;
		DEBUG("water_level=%s  %d", water_level_str, water_level);
	}
	else
	{
		return;
	}

	//更新UI水位值
	rain_level_notify_qt(rain_level);
	water_level_notify_qt(water_level);

#if 0
	if(water_level >= get_water_level_1() && water_level < get_water_level_2()) {	//水位2.2米
		//warn_level_1_t = 0;
		warn_level_2_t = 0;
		warn_level_3_t = 0;
		if(now - warn_level_1_t > get_alarm_interval())	//3小时内不报警
		{
			warn_level_1_t = time(NULL);
			
			//弹出qt注意安全界面
			//trigger_alarm_notify_qt(1);

			//播报注意安全语音
			//start_voice_broadcast(1);

			//上报平台
			gw_alarm_to_server(1, water_level/100.0);	//1级报警
		}
	}
	
	if(water_level >= get_water_level_2() && water_level < get_water_level_3()) {	//水位2.5米
	
		warn_level_1_t = 0;
		//warn_level_2_t = 0;
		warn_level_3_t = 0;
		if(now - warn_level_2_t > get_alarm_interval())	//3小时内不报警
		{
			warn_level_2_t = time(NULL);
			
			//弹窗qt准备转移界面
			//trigger_alarm_notify_qt(2);

			//播报准备转移语音
			//start_voice_broadcast(2);

			//上报平台
			gw_alarm_to_server(2, water_level/100.0);	//2级报警
		}
	}
	
	if(water_level >= get_water_level_3()) {	//水位2.8米
		warn_level_1_t = 0;
		warn_level_2_t = 0;
		//warn_level_3_t = 0;
		if(now - warn_level_3_t > get_alarm_interval())	//3小时内不报警
		{
			warn_level_3_t = time(NULL);
			
			//弹窗qt立即转移界面
			//trigger_alarm_notify_qt(3);

			//播报立即转移语音
			//start_voice_broadcast(3);

			//上报平台
			gw_alarm_to_server(3, water_level/100.0);	//3级报警
		}
	}
#endif

	//反馈RTU 流水号 , 时间
	hydrology_transform_rtu_rsp(pkg, &pkgHead->pkg_data, 8);
}


// only rsp , do nothing
void hydrology_water_level_process_2(unsigned char *pkg)
{
	int pkg_len;
	char water_level_str[16] = {0};
	hydrology_head_t *pkgHead;
	pkgHead = (hydrology_head_t *)pkg;

	pkg_len = get_pkg_data_len(pkg);

	if(pkg_len == 0x26)
	{
		hex2string(water_level_str, &pkg[39], 4);
	}
	else if(pkg_len == 0x2B)
	{
		hex2string(water_level_str, &pkg[39], 4);
	}
	else
	{
		return;
	}
	
	hydrology_transform_rtu_rsp(pkg, &pkgHead->pkg_data, 8);
}

void hydrology_broadcast_task_process(unsigned char *pkg)
{
	char devSN[32] = {0};
	get_pkg_dev_sn(pkg, devSN);

	unsigned char *pkg_data;
	unsigned short pkg_len;

	BROADCASTTASK_RSP_DATA *broadcasttask_rsp_data;

	pkg_len = get_pkg_data_len(pkg);
	pkg_data = get_pkg_data_addr_ptr(pkg);

	if(pkg_len > 0) {
		broadcasttask_rsp_data = (BROADCASTTASK_RSP_DATA *)pkg_data;

		//应答状态保存到文件
		broadcast_task_set_answer(broadcasttask_rsp_data->broadcastTaskId, devSN);

		//更新QT界面
		broadcast_task_answer_update(broadcasttask_rsp_data->broadcastTaskId);
	}
}

void hydrology_analysis(unsigned char *pkg, int data_type)
{
	hydrology_head_t *pkgHead;

	DEBUG("hydrology_analysis data_type:%s", (data_type == DATA_TYPE_MQTT) ? "mqtt":"tpunb");

	pkgHead = (hydrology_head_t *)pkg;
	switch (pkgHead->cmd_type) {
		case HYD_CMD_ALIVE:	//心跳
			hydrology_heartbeat_process(pkg, data_type);
			break;

		case HYD_CMD_WARN://注意安全 准备转移 立即转移	消警 的指令反馈	回复报警类型	是否已应答
			hydrology_warn_process(pkg);
			break;

		case HYD_CMD_SET_NETINFO:	//呼叫器配网
			hydrology_set_dev_netinfo_process(pkg);
			break;

		case HYD_CMD_WARNCANCLE:	//呼叫器按下按键消警,更新应答状态
			hydrology_warn_cancle_process(pkg);
			break;

		case HYD_CMD_RECORD:		//语音包
			//voice_broadcast_rsp();
			break;

		case HYD_CMD_RECORD_END:	//语音包的确认 取消播放
			break;

		case HYD_CMD_BROADCAST_TASK:	//广播任务回应
			hydrology_broadcast_task_process(pkg);
			break;

		case HYD_CMD_TRIGGER_ALARM:	//from rtu
			hydrology_trigger_alarm_process(pkg, data_type);
			break;

		case 0x32://from rtu
			hydrology_water_level_process(pkg);
			break;

		case 0x33://from rtu
			hydrology_water_level_process_2(pkg);
			break;
		default: 
			DEBUG("hydrology_analysis unknow cmd_type:%02X", pkgHead->cmd_type);
			break;
	}
}

void hydrology_voice_end(void)
{
	hydrology_transform(HYD_CMD_RECORD_END, NULL, 0);
}

void hydrology_voice_req(unsigned char *buf, unsigned short length)
{
	hydrology_transform(HYD_CMD_RECORD, buf, length);
}

//void hydrology_voice_req(unsigned char *buf, unsigned short length, bool eof)
//{
//	char send_buf[RECORD_DATA_LEN] = {0};
//	memcpy(send_buf, buf, length);
//	hydrology_transform(HYD_CMD_RECORD, buf, RECORD_DATA_LEN);
//}

static int get_queue_index(unsigned char cmdtype)
{
	//指令放入哪个队列
	switch(cmdtype) {
		case HYD_CMD_RECORD:
		case HYD_CMD_RECORD_END:
			return QUEUE_INDEX_VOICE;

		default:
			return QUEUE_INDEX_DEFAULT;
	}
}

static int get_usec_delay(unsigned char cmdtype)
{
	//发送完指令,等待时间
	switch(cmdtype) {
		case HYD_CMD_RECORD:
		case HYD_CMD_RECORD_END:
			return DELAY_US_300MS;

		case HYD_CMD_GET_ONLINE:
			return DELAY_US_1000MS;

		case HYD_CMD_PICTURE:
			return DELAY_US_1000MS;

		default:
			return DELAY_US_300MS;
	}
}

static int allow_tpunb_send(unsigned char cmdtype)
{
	switch(cmdtype) {
		case HYD_CMD_RECORD:
		case HYD_CMD_RECORD_END:
			return 0;

		default:
			return 1;
	}
}

void hydrology_transform_param_init(hydrology_param_t *hydrology_param, unsigned char cmdtype, unsigned char *buf, unsigned short length)
{
	memset(hydrology_param, 0, sizeof(hydrology_param_t));
	hydrology_param->addr = 0;	//广播数据
	hydrology_param->cmdtype = cmdtype;
	hydrology_param->buf = buf;
	hydrology_param->length = length;
}

void hydrology_transform(unsigned char cmdtype, unsigned char *buf, unsigned short length)
{
	hydrology_param_t hydrology_param;
	hydrology_transform_param_init(&hydrology_param, cmdtype, buf, length);
	hydrology_transform_enqueue(&hydrology_param);
}

void hydrology_message_publish(char *terminal_devsn, unsigned char *msg, int len)
{
	if(strlen(terminal_devsn) == 0) {
		//广播
		gw_publish_broadcast_terminal_message(msg, len);
	} else {
		//点播
		gw_publish_terminal_message(terminal_devsn, msg, len);
	}
}

//推荐使用
void hydrology_transform_enqueue(hydrology_param_t *hydrology_param)
{
	unsigned char *pkg;
	hydrology_head_t *pkgHead;
	unsigned short pkgCrc;
	char to_devsn[32] = {0};
	QueueNode *new_node;

	unsigned char cmdtype;
	unsigned char *buf;
	unsigned short length;


	cmdtype = hydrology_param->cmdtype;
	buf = hydrology_param->buf;
	length = hydrology_param->length;

	pkg = malloc(length + FRAME_PADDING_LEN);
	if (pkg == NULL) {
		return;
	}

	new_node = (QueueNode *)malloc(sizeof(QueueNode));
	if (new_node == NULL) {
		free(pkg);
		return;
	}

	memset(new_node, 0, sizeof(QueueNode));
	new_node->addr = hydrology_param->addr;

	new_node->buf = pkg;							// 存储buf指针
	new_node->next = NULL;							// 新节点是队尾，next为NULL
	new_node->usec_delay = get_usec_delay(cmdtype);	//微妙

	pkgHead = (hydrology_head_t *)pkg;
	pkgHead->header[0] = FRAME_HEAD;
	pkgHead->header[1] = FRAME_HEAD;
	sn_convert(to_devsn, get_gw_sn());
	sn_to_devid(to_devsn, pkgHead->dev_addr.remoter_addrs.remoter_addr);
	
	pkgHead->dev_addr.remoter_addrs.center_addr = 1;
	pkgHead->passwd[0] = 0xA5;
	pkgHead->passwd[1] = 0xA5;
	pkgHead->cmd_type = cmdtype;
	pkgHead->pkg_len[0] = (0x80 | (length >> 8));
	pkgHead->pkg_len[1] = length & 0xFF;
	pkgHead->pkg_begin = FRAME_STX;
	pkg[length + FRAME_PADDING_LEN - 3] = FRAME_ETX;
	if (length)
		memcpy(&(pkgHead->pkg_data), buf, length);
	pkgCrc = do_crc16(pkg, length + FRAME_PADDING_LEN - 2);
	pkg[length + FRAME_PADDING_LEN - 2] = (pkgCrc >> 8);
	pkg[length + FRAME_PADDING_LEN - 1] = (pkgCrc & 0xFF);

	if(allow_tpunb_send(cmdtype)) {
		pthread_mutex_lock(&tpunbStackMutex);
		enqueue_node(get_queue_index(cmdtype), new_node);
		pthread_mutex_unlock(&tpunbStackMutex);
	}

	if(!hydrology_param->prohibit_send_mqtt) {
		hydrology_message_publish(hydrology_param->dev_sn, pkg, length + FRAME_PADDING_LEN);
	}
}


void hydrology_transform_rtu_rsp(unsigned char *pkg_recv, unsigned char *buf, unsigned short length)
{
	unsigned char *pkg;
	hydrology_head_t *pkgHead_send;
	hydrology_head_t *pkgHead_recv;
	unsigned short pkgCrc;
	QueueNode *new_node;
	
	pkg = malloc(length + FRAME_PADDING_LEN);
	if (pkg == NULL) {
		return;
	}

    new_node = (QueueNode *)malloc(sizeof(QueueNode));
	if (new_node == NULL) {
		free(pkg);
		return;
	}

	pkgHead_recv = (hydrology_head_t *)pkg_recv;

    new_node->buf = pkg;    											// 存储buf指针
    new_node->next = NULL;  											// 新节点是队尾，next为NULL
	new_node->usec_delay = get_usec_delay(pkgHead_recv->cmd_type);		//微妙

	pkgHead_send = (hydrology_head_t *)pkg;
	pkgHead_send->header[0] = FRAME_HEAD;
	pkgHead_send->header[1] = FRAME_HEAD;
	memcpy(pkgHead_send->dev_addr.remoter_addrs.remoter_addr, \
			pkgHead_recv->dev_addr.center_addrs.remoter_addr, \
			FRAME_REMOTER_ADDR_LEN);
	
	pkgHead_send->dev_addr.remoter_addrs.center_addr = pkgHead_recv->dev_addr.center_addrs.center_addr;
	pkgHead_send->passwd[0] = pkgHead_recv->passwd[0];
	pkgHead_send->passwd[1] = pkgHead_recv->passwd[1];
	pkgHead_send->cmd_type = pkgHead_recv->cmd_type;
	pkgHead_send->pkg_len[0] = (0x80 | (length >> 8));
	pkgHead_send->pkg_len[1] = length & 0xFF;
	pkgHead_send->pkg_begin = FRAME_STX;
	pkg[length + FRAME_PADDING_LEN - 3] = FRAME_ETX;
	if (length)
		memcpy(&(pkgHead_send->pkg_data), buf, length);
	pkgCrc = do_crc16(pkg, length + FRAME_PADDING_LEN - 2);
	//DEBUG("crc: %04X\n", pkgCrc);
	pkg[length + FRAME_PADDING_LEN - 2] = (pkgCrc >> 8);
	pkg[length + FRAME_PADDING_LEN - 1] = (pkgCrc & 0xFF);

	pthread_mutex_lock(&tpunbStackMutex);
	enqueue_node(get_queue_index(pkgHead_recv->cmd_type), new_node);
	pthread_mutex_unlock(&tpunbStackMutex);
}


unsigned short do_crc16(unsigned char *ptr, int len)
{
	unsigned char i;
	unsigned short crc = 0xFFFF;

	while (len--)
	{
		crc ^= *ptr++;
		for (i = 0; i < 8; ++i)
		{
			if (crc & 1)
				crc = (crc >> 1) ^ 0xA001;
			else
				crc = (crc >> 1);
		}
	}
	
	return crc;
}

